﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Drawing;
using System.Drawing.Drawing2D;


namespace Ehai.Web.Framework.Rules
{
    class CnVerifyCodeRuleHandle:IMsgRuleHandle
    {
        #region IMsgRuleHandle 成员
#if DEBUG
        private int _execStatus = 0;
        public int ExecStatus
        {
            get { return _execStatus; }
        }
#endif
        public const string Name = "cnverifycode";

        #region 产生随机字符串
        
        /// <summary>
        /// 产生随机字符串
        /// </summary>
        /// <param name="num">需要产生的字符数</param>
        /// <returns>随机产生的字符串</returns>
        public string[] GenCode(int num)
        {
            string str = "的一是在不了有和人这中大为上个国我以要他时来用们生到作地于出就分对成会可主发年动同工也能下过子说产种面而方后多定行学法所民得经十三之进着等部度家电力里如水化高自二理起小物现实加量都两体制机当使点从业本去把性好应开它合还因由其些然前外天政四日那社义事平形相全表间样与关各重新线内数正心反你明看原又么利比或但质气第向道命此变条只没结解问意建月公无系军很情者最立代想已通并提直题党程展五果料象员革位入常文总次品式活设及管特件长求老头基资边流路级少图山统接知较将组见计别她手角期根论运农指几九区强放决西被干做必置派层片始却专状育厂京识适属圆包火住调满县局照参红细引听";
            string strPY = "DYSZBLYHRZZDWSGGWYYTSLYMSDZDYCJFDCHKZFNDTGYNXGZSCZMEFHDDXXFSMDJSSZJZDBDJDLLRSHGZELQXWXSJLDLTZJDSDCYBQBXHYKTHHYYQXRQWTZSRNSYSPXXQBJYYGGZXXNSZXFNMKYYMLBHDZQDXDMCBTZMJJWYJYGWXJHQZZLDXYTBTZTDCZWGLXYGWRCWZCPSHSJGTJCQLTJZBLLJSTSTJZJJZJJBTSJQGLYNZJJQQFJXBGZBZPCPSQZZYCJSSSYBHZTMXJZCHXYT";

            char[] chastr = str.ToCharArray();
            char[] chastrPY = strPY.ToCharArray();

            string[] code = { String.Empty, String.Empty };
            Random rd = new Random();
            int i;
            for (i = 0; i < num; i++)
            {
                int j = rd.Next(0, str.Length);
                code[0] += str.Substring(j, 1);
                code[1] += strPY.Substring(j, 1);
            }
            return code;
        }
        #endregion

        #region 颜色相关变量赋值
        
        /// <summary>
        /// 颜色相关变量赋值
        /// </summary>
        /// <param name="p"></param>
        /// <param name="result"></param>
        /// <returns></returns>
        public System.Drawing.Color ChooseColor(string p, System.Drawing.Color result)
        {
            switch (p.Trim())
            {
                case "Silver": { result = Color.Silver; }; break;
                case "Black": { result = Color.Black; }; break;
                case "DarkBlue": { result = Color.DarkBlue; }; break;
                case "Blue": { result = Color.Blue; }; break;
                case "Red": { result = Color.Red; }; break;
                case "DarkRed": { result = Color.DarkRed; }; break;
                case "Navy": { result = Color.Navy; }; break;
                case "Brown": { result = Color.Brown; }; break;
                case "Gray": { result = Color.Gray; }; break;
                case "HotPink": { result = Color.HotPink; }; break;
                case "Yellow": { result = Color.Yellow; }; break;
                case "White": { result = Color.White; }; break;
                default: { result = Color.Silver; }; break;
            }
            return result;
        }
        #endregion

        #region 产生前台验证码图片

        /// <summary>
        /// 产生验证码图片的函数
        /// </summary>
        /// <param name="p">传入相关配置的字符串数组,相关参数详见备注</param>
        /// <param name="checkCodeArr">随机产生的字符串</param>
        /// <param name="ci">相关配置文件</param>
        /// 备注:
        ///0:(必选)处理类型,即CreatCnVerifyCode.<br/>
        ///1:(可选)字符串个数,2-6个,默认为"4"<br/>
        ///2:(可选)背景噪音线的数量,25-50条,默认为"25"<br/>
        ///3:(可选)背景噪音线的颜色,可选项见备注(a),默认为"Silver"<br/>
        ///4:(可选)验证码字体颜色渐变起始色,可选项参见备注(a),默认为"Blue"<br/>
        ///5:(可选)验证码字体颜色渐变结束色,可选项参见备注(a),默认为"DarkRed"<br/>
        ///6:(可选)验证码样式,可选项见备注(c),默认为"Bold"<br/>
        ///7:(可选)验证码宽度,21.5-30,默认长度为"22",具体使用参见备注(d)<br/>
        ///8:(可选)验证码高度,22-30,默认"22",具体使用参见备注(d)<br/>
        ///9:(可选)验证码字体,可选项见备注(b),默认为"Arial"<br/>
        ///10:(可选)验证码字号,12-15,默认为"12"<br/>
        /// <returns>
        /// 状态码,包含在strArr[0][0]中
        /// </returns>
        public string[][] CreateCheckCodeImage(string[] p, string[] checkCodeArr, ContextInfo ci)
        {

            string checkCode = checkCodeArr[0];
            if (checkCode.Trim() == "" || checkCode == null)
                return null;
            ci.Session["Code"] = checkCodeArr[1]; //将字符串保存到Session中，以便需要时进行验证

            //定义及初始化字符串数组用以返回信息
            string[][] strArr;
            strArr = new string[1][] { new string[] { String.Empty, String.Empty } };

            int bgLine = Convert.ToInt16(p[2].Trim());
            System.Drawing.Color bgLineColor = Color.Silver;
            bgLineColor = ChooseColor(p[3], bgLineColor);
            System.Drawing.Color FontStartColor = Color.Blue;
            FontStartColor = ChooseColor(p[4], FontStartColor);
            System.Drawing.Color FontEndColor = Color.DarkRed;
            FontEndColor = ChooseColor(p[5], FontEndColor);
            System.Drawing.FontStyle FontStyle = FontStyle.Bold;
            switch (p[6].Trim())
            {
                case "Bold": { FontStyle = FontStyle.Bold; }; break;
                case "Italic": { FontStyle = FontStyle.Italic; }; break;
                case "Underline": { FontStyle = FontStyle.Underline; }; break;
                default: { FontStyle = FontStyle.Bold; }; break;
            }
            int FontWidth = Convert.ToInt16(p[7].Trim());
            int FontHeight = Convert.ToInt16(p[8].Trim());
            string FontFamily = p[9].Trim();
            int FontSize = Convert.ToInt16(p[10].Trim());

            System.Drawing.Bitmap image = new System.Drawing.Bitmap((int)(checkCode.Length * FontWidth), FontHeight);
            Graphics g = Graphics.FromImage(image);
            try
            {
                //生成随机生成器
                Random random = new Random();

                //清空图片背景色
                g.Clear(Color.White);

                // 画图片的背景噪音线
                int i;
                for (i = 0; i < bgLine; i++)
                {
                    int x1 = random.Next(image.Width);
                    int x2 = random.Next(image.Width);
                    int y1 = random.Next(image.Height);
                    int y2 = random.Next(image.Height);
                    g.DrawLine(new Pen(bgLineColor), x1, y1, x2, y2);
                }

                Font font = new System.Drawing.Font(FontFamily, FontSize, (FontStyle));
                System.Drawing.Drawing2D.LinearGradientBrush brush = new System.Drawing.Drawing2D.LinearGradientBrush(new Rectangle(0, 0, image.Width, image.Height), FontStartColor, FontEndColor, 1.2F, true);
                g.DrawString(checkCode, font, brush, 2, 2);

                //画图片的前景噪音点
                g.DrawRectangle(new Pen(Color.Silver), 0, 0, image.Width - 1, image.Height - 1);
                System.IO.MemoryStream ms = new System.IO.MemoryStream();

                image.Save(ms, System.Drawing.Imaging.ImageFormat.Gif);

                ci.Response.ClearContent();
                ci.Response.ContentType = "image/Gif";
                ci.Response.BinaryWrite(ms.ToArray());

                strArr[0][0] = "201";

                return strArr;

            }
            catch
            {
                g.Dispose();
                image.Dispose();
            }
            return null;
        }
        #endregion

        /// <summary>
        /// 产生中文验证码,可控制前台验证码图片部分属性(见参数列表)
        /// </summary>
        /// <param name="p">
        ///0:(必选)处理类型,即"CreatCnVerifyCode"<br/>
        ///1:(可选)字符串个数,2-6个,默认为"4"<br/>
        ///2:(可选)背景噪音线的数量,25-50条,默认为"25"<br/>
        ///3:(可选)背景噪音线的颜色,可选项见备注(a),默认为"Silver"<br/>
        ///4:(可选)验证码字体颜色渐变起始色,可选项参见备注(a),默认为"Blue"<br/>
        ///5:(可选)验证码字体颜色渐变结束色,可选项参见备注(a),默认为"DarkRed"<br/>
        ///6:(可选)验证码样式,可选项见备注(c),默认为"Bold"<br/>
        ///7:(可选)验证码宽度,21.5-30,默认长度为"22",具体使用参见备注(d)<br/>
        ///8:(可选)验证码高度,22-30,默认"22",具体使用参见备注(d)<br/>
        ///9:(可选)验证码字体,可选项见备注(b),默认为"Arial"<br/>
        ///10:(可选)验证码字号,12-15,默认为"12"<br/>
        ///</param>
        ///<param name="ci">环境变量</param>
        ///备注:
        ///(a)所有的颜色选项值,均来自System.Drawing.Color属性,在此仅列出常用10余类颜色值供挑选,颜色类型可在日后的版本升级中增加
        ///   可选颜色Black,Blue,DarkBlue,,Red,DarkRed,Silver,Navy,Brown,Gray,HotPink,Yellow,White
        ///(b)所有字体取自系统字体,除Arial外还可以使用宋体,黑体,微软雅黑,幼圆,楷体,隶书
        ///(c)字体样式包括加粗Bold,斜体Italic及下划线Underline
        ///(d)验证码图片总宽度计算公式为:字符串长度*验证码宽度,故图片长度不仅于验证码长度有关,也与验证码字符数目有关;高度可自设,建议不超过30
        /// <returns>状态值，包含在strArr[0][0]</returns>
        public string[][] Execute(string[] p, ContextInfo ci)
        {

            if (p.Length < 1 || p.Length > 11)
            {
#if DEBUG
                _execStatus = -2;
#endif
                return null;
            }

            if (p[0].Trim() == string.Empty)
            {
#if DEBUG
                _execStatus = 1;
#endif
                return null;
            }

            string[] t = new string[] { String.Empty, String.Empty, String.Empty, String.Empty, String.Empty, String.Empty, String.Empty, String.Empty, String.Empty, String.Empty, String.Empty };

            t[1] = p.Length > 1 ? p[1] : "4";
            if (t[1].Trim() == string.Empty) { t[1] = "4"; }
            t[2] = p.Length > 2 ? p[2] : "25";
            if (t[2].Trim() == string.Empty) { t[2] = "25"; }
            t[3] = p.Length > 3 ? p[3] : "Silver";
            if (t[3].Trim() == string.Empty) { t[3] = "Silver"; }
            t[4] = p.Length > 4 ? p[4] : "Blue";
            if (t[4].Trim() == string.Empty) { t[4] = "Blue"; }
            t[5] = p.Length > 5 ? p[5] : "DarkRed";
            if (t[5].Trim() == string.Empty) { t[5] = "DarkRed"; }
            t[6] = p.Length > 6 ? p[6] : "Bold";
            if (t[6].Trim() == string.Empty) { t[6] = "Bold"; }
            t[7] = p.Length > 7 ? p[7] : "22";
            if (t[7].Trim() == string.Empty) { t[7] = "22"; }
            t[8] = p.Length > 8 ? p[8] : "22";
            if (t[8].Trim() == string.Empty) { t[8] = "22"; }
            t[9] = p.Length > 9 ? p[9] : "Arial";
            if (t[9].Trim() == string.Empty) { t[9] = "Arial"; }
            t[10] = p.Length > 10 ? p[10] : "12";
            if (t[10].Trim() == string.Empty) { t[10] = "12"; }

            int CodeNum = Convert.ToInt16(t[1].Trim());

            string[] Code = GenCode(CodeNum);
#if DEBUG
            _execStatus = 0;
#endif
            return CreateCheckCodeImage(t, Code, ci);
        }

        public string GetHelpInfo()
        {
            return "生成验证码";
        }

        public string GetHelpDetail()
        {
            return "例1:{ \"CreatCnVerifyCode\" };备注:(a)所有的颜色选项值,均来自System.Drawing.Color属性,在此仅列出常用10余类颜色值供挑选,颜色类型可在日后的版本升级中增加.可选颜色Black,Blue,DarkBlue,,Red,DarkRed,Silver,Navy,Brown,Gray,HotPink,Yellow,White<br/>(b)所有字体取自系统字体,除Arial外还可以使用宋体,黑体,微软雅黑,幼圆,楷体,隶书<br/>(c)字体样式包括加粗Bold,斜体Italic及下划线Underline<br/>(d)验证码图片总宽度计算公式为:字符串长度*验证码宽度,故图片长度不仅于验证码长度有关,也与验证码字符数目有关;高度可自设,建议不超过30";
        }

        public string[] GetParametersInfo()
        {
            string[] t = new string[11];
            t[0] = "(必选)处理类型,即\"CreatCnVerifyCode\"";
            t[1] = "(可选)字符串个数,2-6个,默认为\"4\"";
            t[2] = "(可选)背景噪音线的数量,25-50条,默认为\"25\"";
            t[3] = "(可选)背景噪音线的颜色,可选项见备注(a),默认为\"Silver\"";
            t[4] = "(可选)验证码字体颜色渐变起始色,可选项参见备注(a),默认为\"Blue\"";
            t[5] = "(可选)验证码字体颜色渐变结束色,可选项参见备注(a),默认为\"DarkRed\"";
            t[6] = "(可选)验证码样式,可选项见备注(c),默认为\"Bold\"";
            t[7] = "(可选)验证码宽度,21-30,默认长度为\"22\",具体使用参见备注(d)";
            t[8] = "(可选)验证码高度,22-30,默认\"22\",具体使用参见备注(d)";
            t[9] = "(可选)验证码字体,可选项见备注(b),默认为\"Arial\"";
            t[10] = "(可选)验证码字号,12-15,默认为\"12\"";
            return t;
        }

        #endregion
    }
}
